
import logging


class BasicLogger:
    def __init__(self):
        self.level = logging.NOTSET
        self.enabled = True

    def _setEnable(self, enabled):
        self.enabled = enabled

    def _setLevel(self, level):
        self.level = level

    def debug(self, str_):
        if self.enabled and self.level <= logging.DEBUG:
            logging.debug(str_)

    def info(self, str_):
        if self.enabled and self.level <= logging.INFO:
            logging.info(str_)

    def warn(self, str_):
        if self.enabled and self.level <= logging.WARNING:
            logging.warning(str_)

    def critic(self, str_):
        if self.enabled and self.level <= logging.CRITICAL:
            logging.critical(str_)

    def error(self, str_):
        if self.enabled and self.level <= logging.ERROR:
            logging.error(str_)

    def shutdown(self):
        logging.shutdown()

    def reset(self, logfile, filename, level=logging.NOTSET, template=None):
        if template is None:
            template = '%(asctime)s [%(levelname)s] %(message)s'

        if logfile:
            logging.basicConfig(level=level, format=template,
                                filename=filename)
        else:
            logging.basicConfig(level=level, format=template)


class Logger:
    def __init__(self, logfile, filename, level=0, template=None):
        self.logger = BasicLogger()

        # always set the level to the maximum due to the reset of logging
        try:
            self.logger.reset(logfile, filename, logging.NOTSET, template)
        except IOError:
            self.logger._setEnable(False)

        self.setlevel(level)

        # map the method of BasicLogger
        for name in BasicLogger.__dict__:
            if not name.startswith('_'):
                self.__dict__[name] = getattr(self.logger, name)

    def __del__(self):
        self.shutdown()

    def __mapLevel(self, level):
        if level == 0:
            lv = logging.CRITICAL
        elif level == 1:
            lv = logging.ERROR
        elif level == 2:
            lv = logging.WARNING
        elif level == 3:
            lv = logging.INFO
        elif level == 4:
            lv = logging.DEBUG
        else:
            lv = logging.NOTSET

        return lv

    def setlevel(self, level):
        self.level = self.__mapLevel(level)
        self.logger._setLevel(self.level)

    def getLogger(self):
        return self.logger

    def printf(self, str_):
        if self.level <= logging.DEBUG:
            self.debug(str_)
        elif self.level <= logging.INFO:
            self.error(str_)
        elif self.level <= logging.WARNING:
            self.warn(str_)
        elif self.level <= logging.ERROR:
            self.error(str_)
        elif self.level <= logging.CRITICAL:
            self.critic(str_)
